

open Ast

let rec test_list func = function
	| [] -> false
	| a::b -> (func a) || (test_list func b)

let rec is_label_used_in_statement label = function
	| ABlock block -> is_label_used_in_block label block
	| AVariableStatement _ -> false
	| AConstStatement _ -> false
	| AFuncDeclaration _ -> false
	| AEmptyStatement -> false
	| AExpressionStatement es -> false
	| AIfStatement is -> is_label_used_in_ifStatement label is
	| AIterationStatement is -> is_label_used_in_iterationStatement label is
	| AContinueStatement cs -> (match cs with
		| None -> false
		| Some ident -> ident = label)
	| ABreakStatement bs -> (match bs with
		| None -> false
		| Some ident -> ident = label)
	| AReturnStatement rs -> false
	| AWithStatement (_,stmt) -> is_label_used_in_statement label stmt
	| ALabelledStatement (_,stmt) -> is_label_used_in_statement label stmt
	| ASwitchStatement (_,caseBlock) -> is_label_used_in_caseBlock label caseBlock
	| AThrowStatement ts -> false
	| ATryStatement ts -> is_label_used_in_tryStatement label ts
	| ADebuggerStatement -> false

and is_label_used_in_block label block =
	test_list (is_label_used_in_statement label) block

and is_label_used_in_ifStatement label = function
	| AIfElse (_, stmt1, stmt2) -> (is_label_used_in_statement label stmt1) || (is_label_used_in_statement label stmt2)
	| AIf (_, stmt) -> is_label_used_in_statement label stmt

and is_label_used_in_iterationStatement label = function
	| ADoWhile (stmt,_) -> is_label_used_in_statement label stmt
	| AWhile (_, stmt) -> is_label_used_in_statement label stmt
	| AFor (_,_,_,stmt) -> is_label_used_in_statement label stmt
	| AForVar (_,_,_,_,stmt) -> is_label_used_in_statement label stmt
	| AForIn (_,_,stmt) -> is_label_used_in_statement label stmt
	| AForVarIn (_,_,_,stmt) -> is_label_used_in_statement label stmt
	
and is_label_used_in_caseBlock label = function
	| ACasesNoDefault caseClauses -> test_list (is_label_used_in_caseClause label) caseClauses
	| ACasesDefault (caseClauses1, defaultClause, caseClauses2) ->
		(test_list (is_label_used_in_caseClause label) caseClauses1)
		|| (is_label_used_in_block label defaultClause)
		|| (test_list (is_label_used_in_caseClause label) caseClauses2)

and is_label_used_in_caseClause label (_,stmts) = 
	test_list (is_label_used_in_statement label) stmts

and is_label_used_in_tryStatement label = function
	| ATryCatch (block1, (_,block2)) -> 
		(is_label_used_in_block label block1) 
		|| (is_label_used_in_block label block2)
	| ATryFinally (block1, block2) -> 
		(is_label_used_in_block label block1) 
		|| (is_label_used_in_block label block2)
	| ATryCatchFinally (block1, (_,block2), block3) -> 
		(is_label_used_in_block label block1) 
		|| (is_label_used_in_block label block2)
		|| (is_label_used_in_block label block3)
		
